{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "UWvrShlZjZwr"
   },
   "source": [
    "# Serving Text Classification Using Keras on AI Platform\n",
    "\n",
    "\n",
    "## Overview\n",
    "\n",
    "This notebook illustrates the new feature of serving custom model prediction code on AI Platform. It allows us to execute arbitrary python pre-processing code prior to invoking a model, as well as post-processing on the produced predictions.\n",
    "\n",
    "This is all done server-side so that the client can pass data directly to AI Platform Serving in the unprocessed state.\n",
    "\n",
    "We will take advantage of this for text classification because it involves pre-processing that is not easily accomplished using native TensorFlow. Instead we will execute the the non TensorFlow pre-processing via python code on the server side.\n",
    "\n",
    "We implement our Text Classifier using Keras. Keras is a high-level API for building and training deep learning models. [tf.keras](https://www.tensorflow.org/guide/keras) is TensorFlow’s implementation of this API. To learn more about building machine learning models in Keras more generally, read [TensorFlow's Keras tutorials](https://www.tensorflow.org/tutorials/keras).\n",
    "\n",
    "\n",
    "## Dataset\n",
    "[Hacker News](https://bigquery.cloud.google.com/table/fh-bigquery:hackernews.stories) is one of many public datasets available in [BigQuery](https://cloud.google.com/bigquery). This dataset includes titles of articles from several data sources. For the following tutorial, we extracted the titles that belong to either GitHub, The New York Times, or TechCrunch, and saved them as CSV files in a publicly shared Cloud Storage bucket at the following location: **gs://cloud-training-demos/blogs/CMLE_custom_prediction**\n",
    "\n",
    "## Objective\n",
    "The goal of this tutorial is to:\n",
    "1. Process the data for text classification.\n",
    "2. Train a Keras Text Classifier (locally).\n",
    "3. Deploy the Keras Text Classifier, along with the preprocessing artifacts, to AI Platform Serving, using the Custom Online Prediction code.\n",
    "\n",
    "This tutorial focuses more on using this model with AI Platform Serving than on the design of the text classification model itself. For more details about text classification, please refer to [Google developer's Guide to Text Classification](https://developers.google.com/machine-learning/guides/text-classification/). \n",
    "\n",
    "## Costs\n",
    "This tutorial uses billable components of Google Cloud Platform (GCP):\n",
    "1. AI Platform Serving (Cloud Machine Learning Engine)\n",
    "2. Cloud Storage\n",
    "Learn about AI Platform Serving pricing and Cloud Storage pricing, and use the Pricing Calculator to generate a cost estimate based on your projected usage.\n",
    "\n",
    "\n",
    "<a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/cloudml-samples/blob/main/notebooks/keras/Text%20Classification%20Using%20Keras%20and%20CMLE.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**If you are using AI Platform Notebooks**, your environment is already\n",
    "authenticated. Skip this step."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "66JlKmfzvPhN"
   },
   "outputs": [],
   "source": [
    "try:\n",
    " from google.colab import auth\n",
    " auth.authenticate_user()\n",
    "except:\n",
    " pass"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "eQWHJ3X7vLeQ"
   },
   "source": [
    "## Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "lBFAoHPAJNMO"
   },
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "N0p05OnXRugd"
   },
   "outputs": [],
   "source": [
    "!pip install tensorflow==1.13.1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "bupGswGOcMW2"
   },
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "print(tf.__version__) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "ewdEsJuVvNqm"
   },
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "PROJECT='' # SET TO YOUR GCP PROJECT NAME\n",
    "BUCKET='' # SET TO YOUR GCS BUCKET NAME\n",
    "ROOT='keras_text_classification'\n",
    "MODEL_DIR=os.path.join(ROOT,'models')\n",
    "PACKAGES_DIR=os.path.join(ROOT,'packages')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "2utHS2nnzKty"
   },
   "outputs": [],
   "source": [
    "!gcloud config set project {PROJECT}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "dNRtpAzclhBe"
   },
   "outputs": [],
   "source": [
    "# Delete any previous artefacts from Google Cloud Storage\n",
    "!gsutil rm -r gs://{BUCKET}/{ROOT}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "V12s5BFCkYhC"
   },
   "source": [
    "## Download and Explore Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "ww6dAQ7EkHzZ"
   },
   "outputs": [],
   "source": [
    "# Download from Google Cloud Storage\n",
    "%%bash\n",
    "gsutil cp gs://cloud-training-demos/blogs/CMLE_custom_prediction/keras_text_pre_processing/train.tsv .\n",
    "gsutil cp gs://cloud-training-demos/blogs/CMLE_custom_prediction/keras_text_pre_processing/eval.tsv ."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "g1XEyk4toH76"
   },
   "outputs": [],
   "source": [
    "!head eval.tsv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "bHqYoDlFsw02"
   },
   "source": [
    "## Preprocessing"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "yIarI3u3r6vd"
   },
   "source": [
    "### Pre-processing class to be used in both training and serving"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "GdkNipQtr8-P"
   },
   "outputs": [],
   "source": [
    "%%writefile preprocess.py\n",
    "\n",
    "from tensorflow.python.keras.preprocessing import sequence\n",
    "from tensorflow.keras.preprocessing import text\n",
    "\n",
    "class TextPreprocessor(object):\n",
    "  def __init__(self, vocab_size, max_sequence_length):\n",
    "    self._vocab_size = vocab_size\n",
    "    self._max_sequence_length = max_sequence_length\n",
    "    self._tokenizer = None\n",
    "\n",
    "  def fit(self, text_list):        \n",
    "    # Create vocabulary from input corpus.\n",
    "    tokenizer = text.Tokenizer(num_words=self._vocab_size)\n",
    "    tokenizer.fit_on_texts(text_list)\n",
    "    self._tokenizer = tokenizer\n",
    "\n",
    "  def transform(self, text_list):        \n",
    "    # Transform text to sequence of integers\n",
    "    text_sequence = self._tokenizer.texts_to_sequences(text_list)\n",
    "\n",
    "    # Fix sequence length to max value. Sequences shorter than the length are\n",
    "    # padded in the beginning and sequences longer are truncated\n",
    "    # at the beginning.\n",
    "    padded_text_sequence = sequence.pad_sequences(\n",
    "      text_sequence, maxlen=self._max_sequence_length)\n",
    "    return padded_text_sequence"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "pEk_bHo08a1n"
   },
   "source": [
    "### Test Prepocessing Locally"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "sKtHuVUw8kFO"
   },
   "outputs": [],
   "source": [
    "from preprocess import TextPreprocessor\n",
    "\n",
    "processor = TextPreprocessor(5, 5)\n",
    "processor.fit(['hello machine learning'])\n",
    "processor.transform(['hello machine learning'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "lsTGmBn4s2fC"
   },
   "source": [
    "## Model Creation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "eFKEHCk_WYQU"
   },
   "source": [
    "### Metadata"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "P-1_lAwsWNFf"
   },
   "outputs": [],
   "source": [
    "CLASSES = {'github': 0, 'nytimes': 1, 'techcrunch': 2}  # label-to-int mapping\n",
    "VOCAB_SIZE = 20000  # Limit on the number vocabulary size used for tokenization\n",
    "MAX_SEQUENCE_LENGTH = 50  # Sentences will be truncated/padded to this length"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "jkzmfu3jV-78"
   },
   "source": [
    "### Prepare data for training and evaluation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "HDX_3jquWCBY"
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "from preprocess import TextPreprocessor\n",
    "\n",
    "def load_data(train_data_path, eval_data_path):\n",
    "    # Parse CSV using pandas\n",
    "    column_names = ('label', 'text')\n",
    "    df_train = pd.read_csv(\n",
    "      train_data_path, names=column_names, sep='\\t').sample(frac=1)\n",
    "    df_eval = pd.read_csv(\n",
    "      eval_data_path, names=column_names, sep='\\t')\n",
    "\n",
    "    return ((list(df_train['text']), np.array(df_train['label'].map(CLASSES))),\n",
    "            (list(df_eval['text']), np.array(df_eval['label'].map(CLASSES))))\n",
    "\n",
    "\n",
    "((train_texts, train_labels), (eval_texts, eval_labels)) = load_data(\n",
    "       'train.tsv', 'eval.tsv')\n",
    "\n",
    "# Create vocabulary from training corpus.\n",
    "processor = TextPreprocessor(VOCAB_SIZE, MAX_SEQUENCE_LENGTH)\n",
    "processor.fit(train_texts)\n",
    "\n",
    "# Preprocess the data\n",
    "train_texts_vectorized = processor.transform(train_texts)\n",
    "eval_texts_vectorized = processor.transform(eval_texts)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "MakbLwTbuMsZ"
   },
   "source": [
    "### Save pre-processing object\n",
    "\n",
    "We need to save this so the same tokenizer used at training can be used to pre-process during serving"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "sziwQgs0uZzx"
   },
   "outputs": [],
   "source": [
    "import pickle\n",
    "\n",
    "with open('./processor_state.pkl', 'wb') as f:\n",
    "  pickle.dump(processor, f)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "r9sDfoXesC1d"
   },
   "source": [
    "### Build the model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "E7hifM2esEe9"
   },
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "\n",
    "from tensorflow.keras import models\n",
    "from tensorflow.keras.layers import Dense\n",
    "from tensorflow.keras.layers import Dropout\n",
    "from tensorflow.keras.layers import Embedding\n",
    "from tensorflow.keras.layers import Conv1D\n",
    "from tensorflow.keras.layers import MaxPooling1D\n",
    "from tensorflow.keras.layers import GlobalAveragePooling1D\n",
    "\n",
    "\n",
    "tf.logging.set_verbosity(tf.logging.INFO)\n",
    "\n",
    "#keras model\n",
    "\n",
    "def create_model(vocab_size, embedding_dim, \n",
    "  filters, kernel_size, dropout_rate, pool_size):\n",
    "  \n",
    "  model = models.Sequential()\n",
    "  model.add(Embedding(input_dim=vocab_size,\n",
    "                          output_dim=embedding_dim,\n",
    "                          input_length=MAX_SEQUENCE_LENGTH))\n",
    "\n",
    "  model.add(Dropout(rate=dropout_rate))\n",
    "  model.add(Conv1D(filters=filters,\n",
    "                            kernel_size=kernel_size,\n",
    "                            activation='relu',\n",
    "                            bias_initializer='random_uniform',\n",
    "                            padding='same'))\n",
    "\n",
    "  model.add(MaxPooling1D(pool_size=pool_size))\n",
    "  model.add(Conv1D(filters=filters * 2,\n",
    "                            kernel_size=kernel_size,\n",
    "                            activation='relu',\n",
    "                            bias_initializer='random_uniform',\n",
    "                            padding='same'))\n",
    "  model.add(GlobalAveragePooling1D())\n",
    "  model.add(Dropout(rate=dropout_rate))\n",
    "  model.add(Dense(len(CLASSES), activation='softmax'))\n",
    "\n",
    "  return model\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "53Gef0A4sjdV"
   },
   "source": [
    "### Train and save the model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "HBoFm2yrslU1"
   },
   "outputs": [],
   "source": [
    "LEARNING_RATE=.001\n",
    "EMBEDDING_DIM=200\n",
    "FILTERS=64\n",
    "KERNEL_SIZE=3\n",
    "DROPOUT_RATE=0.2\n",
    "POOL_SIZE=3\n",
    "\n",
    "NUM_EPOCH=1\n",
    "BATCH_SIZE=128\n",
    "\n",
    "model = create_model(VOCAB_SIZE, EMBEDDING_DIM, \n",
    "  FILTERS, KERNEL_SIZE, DROPOUT_RATE,POOL_SIZE)\n",
    "\n",
    "# Compile model with learning parameters.\n",
    "optimizer = tf.keras.optimizers.Adam(lr=LEARNING_RATE)\n",
    "model.compile(\n",
    "  optimizer=optimizer, loss='sparse_categorical_crossentropy', metrics=['acc'])\n",
    "\n",
    "#keras train\n",
    "model.fit(\n",
    "  train_texts_vectorized, train_labels, epochs=NUM_EPOCH, batch_size=BATCH_SIZE)\n",
    "print('Eval loss/accuracy:{}'.format(\n",
    "  model.evaluate(eval_texts_vectorized, eval_labels, batch_size=BATCH_SIZE)))\n",
    "\n",
    "#save model\n",
    "model.save('keras_saved_model.h5')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "4AWJZP3stCta"
   },
   "source": [
    "## Custom Model Prediction Preparation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "KeR_jDYjuymX"
   },
   "source": [
    "### Copy model and pre-processing object to GCS"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "OJwsuGK3ub4S"
   },
   "outputs": [],
   "source": [
    "!gsutil cp keras_saved_model.h5 gs://{BUCKET}/{MODEL_DIR}/\n",
    "!gsutil cp processor_state.pkl gs://{BUCKET}/{MODEL_DIR}/"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "DZ0H1GKAueAp"
   },
   "source": [
    "### Define Model Class"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "xLvpSsMiufVr"
   },
   "outputs": [],
   "source": [
    "%%writefile model_prediction.py\n",
    "\n",
    "import os\n",
    "import pickle\n",
    "import numpy as np\n",
    "\n",
    "\n",
    "class CustomModelPrediction(object):\n",
    "\n",
    "  def __init__(self, model, processor):\n",
    "    self._model = model\n",
    "    self._processor = processor\n",
    "\n",
    "  def _postprocess(self, predictions):\n",
    "    labels = ['github', 'nytimes', 'techcrunch']\n",
    "    label_indexes = [np.argmax(prediction) for prediction in predictions]\n",
    "    return [labels[label_index] for label_index in label_indexes]\n",
    "\n",
    "\n",
    "  def predict(self, instances, **kwargs):\n",
    "    preprocessed_data = self._processor.transform(instances)\n",
    "    predictions =  self._model.predict(preprocessed_data)\n",
    "    labels = self._postprocess(predictions)\n",
    "    return labels\n",
    "\n",
    "\n",
    "  @classmethod\n",
    "  def from_path(cls, model_dir):\n",
    "    import tensorflow.keras as keras\n",
    "    model = keras.models.load_model(\n",
    "      os.path.join(model_dir,'keras_saved_model.h5'))\n",
    "    with open(os.path.join(model_dir, 'processor_state.pkl'), 'rb') as f:\n",
    "      processor = pickle.load(f)\n",
    "\n",
    "    return cls(model, processor)\n",
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "kL-jv3GDg_zD"
   },
   "source": [
    "### Test Model Class Locally"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "ynL_ovR32Od0"
   },
   "outputs": [],
   "source": [
    "# Headlines for Predictions\n",
    "\n",
    "techcrunch=[\n",
    "  'Uber shuts down self-driving trucks unit',\n",
    "  'Grover raises €37M Series A to offer latest tech products as a subscription',\n",
    "  'Tech companies can now bid on the Pentagon’s $10B cloud contract'\n",
    "]\n",
    "nytimes=[\n",
    "  '‘Lopping,’ ‘Tips’ and the ‘Z-List’: Bias Lawsuit Explores Harvard’s Admissions',\n",
    "  'A $3B Plan to Turn Hoover Dam into a Giant Battery',\n",
    "  'A MeToo Reckoning in China’s Workplace Amid Wave of Accusations'\n",
    "]\n",
    "github=[\n",
    "  'Show HN: Moon – 3kb JavaScript UI compiler',\n",
    "  'Show HN: Hello, a CLI tool for managing social media',\n",
    "  'Firefox Nightly added support for time-travel debugging'\n",
    "]\n",
    "requests = (techcrunch+nytimes+github)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "zx53zlPK6YIK"
   },
   "outputs": [],
   "source": [
    "from model_prediction import CustomModelPrediction\n",
    "\n",
    "classifier = CustomModelPrediction.from_path('.')\n",
    "results = classifier.predict(requests)\n",
    "results"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Q4BEQqoGyZP1"
   },
   "source": [
    "### Package up files and copy to GCS"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "DgQ9UJG_u6Jk"
   },
   "outputs": [],
   "source": [
    "%%writefile setup.py\n",
    "\n",
    "from setuptools import setup\n",
    "\n",
    "setup(\n",
    "  name=\"my_package\",\n",
    "  version=\"0.1\",\n",
    "  include_package_data=True,\n",
    "  scripts=[\"preprocess.py\", \"model_prediction.py\"]\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "IjwWftmpybCI"
   },
   "outputs": [],
   "source": [
    "!python setup.py sdist\n",
    "!gsutil cp ./dist/my_package-0.1.tar.gz gs://{BUCKET}/{PACKAGES_DIR}/my_package-0.1.tar.gz"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "pU4D8prVtLNI"
   },
   "source": [
    "## Model Deployment to CMLE"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "WUEA9FKcy8fM"
   },
   "outputs": [],
   "source": [
    "MODEL_NAME='keras_text_classification'\n",
    "VERSION_NAME='v201903'\n",
    "RUNTIME_VERSION='1.13'\n",
    "REGION='us-central1'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "JBao9v7e1OU0"
   },
   "outputs": [],
   "source": [
    "!gcloud ai-platform models create {MODEL_NAME} --regions {REGION}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "YpZkN4o71PUY"
   },
   "outputs": [],
   "source": [
    "!gcloud ai-platform versions delete {VERSION_NAME} --model {MODEL_NAME} --quiet # run if version already created"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "WbE2cKVE1PaX"
   },
   "outputs": [],
   "source": [
    "!gcloud beta ai-platform versions create {VERSION_NAME} --model {MODEL_NAME} \\\n",
    "--origin=gs://{BUCKET}/{MODEL_DIR}/ \\\n",
    "--python-version=3.5 \\\n",
    "--runtime-version={RUNTIME_VERSION} \\\n",
    "--framework='SCIKIT_LEARN' \\\n",
    "--package-uris=gs://{BUCKET}/{PACKAGES_DIR}/my_package-0.1.tar.gz \\\n",
    "--prediction-class=model_prediction.CustomModelPrediction"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Jn6EFbPUzUTm"
   },
   "source": [
    "## Online Predictions from CMLE"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 51
    },
    "colab_type": "code",
    "id": "mNFvql_-zC4N",
    "outputId": "abd6738d-dfce-4be2-e23d-e9e4c137310f"
   },
   "outputs": [],
   "source": [
    "from googleapiclient import discovery\n",
    "from oauth2client.client import GoogleCredentials\n",
    "import json\n",
    "\n",
    "# JSON format the requests\n",
    "request_data = {'instances': requests}\n",
    "\n",
    "# Authenticate and call CMLE prediction API \n",
    "credentials = GoogleCredentials.get_application_default()\n",
    "api = discovery.build(\n",
    "  'ml', 'v1', credentials=credentials,\n",
    "  discoveryServiceUrl='https://storage.googleapis.com/cloud-ml/discovery/ml_v1_discovery.json')\n",
    "\n",
    "parent = 'projects/{}/models/{}/versions/{}'.format(PROJECT, MODEL_NAME, VERSION_NAME)\n",
    "print(\"Model full name: {}\".format(parent))\n",
    "response = api.projects().predict(body=request_data, name=parent).execute()\n",
    "\n",
    "print(response['predictions'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "5suq2zMMzqPo"
   },
   "source": [
    "## License"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "vOpXERCeztV8"
   },
   "source": [
    "Authors: Khalid Salama & Vijay Reddy \n",
    "\n",
    "---\n",
    "**Disclaimer**: This is not an official Google product. The sample code provided for an educational purpose.\n",
    "\n",
    "---\n",
    "\n",
    "Copyright 2019 Google LLC\n",
    "\n",
    "Licensed under the Apache License, Version 2.0 (the \"License\");\n",
    "you may not use this file except in compliance with the License.\n",
    "You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.\n",
    "\n",
    "Unless required by applicable law or agreed to in writing, software\n",
    "distributed under the License is distributed on an \"AS IS\" BASIS,\n",
    "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
    "See the License for the specific language governing permissions and\n",
    "limitations under the License."
   ]
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [],
   "name": "Text Classification Using Keras and CMLE.ipynb",
   "provenance": [],
   "toc_visible": true,
   "version": "0.3.2"
  },
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
